using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Text;
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using GameFramework.common;
using LitJson;
using NettyDeomo;
using NettyDeomo.entity;
using NettyDeomo.handler;
using NettyDeomo.msg;
using UnityEngine;
using UnityEngine.Serialization;
using Object = System.Object;

//状态同步参考文章：https://www.zhihu.com/people/Coder27/posts
public class NettyClient : MonoSingleton<NettyClient>
{
    public string host;

    public int port;
    private IChannel channel;
    private IEventLoopGroup group;
    public bool isRunning = false;



    // private MessageHandler Handler = new MessageHandler();
    private MsgCodecs Handler = new MsgCodecs();

    #region Client
    public void disconnect()
    {


        if (!isRunning)
        {
            return;
        }
        
        channel.CloseAsync();
        group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1));
        isRunning = false;
        channel = null;
        group = null;
    }

    public async void connectServer()
    {
        
        if (isRunning)
        {
            Debug.LogError("服务器连接中！");
            return;
        }
        group = new MultithreadEventLoopGroup();

        var bootstrap = new Bootstrap();
        bootstrap
            .Group(group)
            .Channel<TcpSocketChannel>()
            .Option(ChannelOption.TcpNodelay, true)
            .Handler(new ActionChannelInitializer<ISocketChannel>(channel =>
            {
                IChannelPipeline pipeline = channel.Pipeline;
                pipeline.AddLast(Handler);
            }));
        channel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse(host), port));
        isRunning = true;
        
    }
    


    #endregion
    
    private void OnGUI()
    {
        if (GUI.Button(new Rect(20, 20, 80, 20), "连接服务器"))
        {
            connectServer();
        }
        if (GUI.Button(new Rect(120, 20, 80, 20), "断开服务器"))
        {
            disconnect();
        }
    }

    public bool sendMessage(object message)
    {
        if (message == null)
        {
            return false;
        }

        if (channel == null)
        {
            Debug.LogError("未连接到服务器");
            return false;
        }

        if (!channel.Active)
        {
            Debug.LogError("连接处于非活动状态");
            return false;
        }

        MsgWrapper msgWrapper = MsgManager.getInstance().createMsgWrapper(message);
        if (msgWrapper != null)
        {
            Debug.Log("发送消息："+message.GetType().Name+" 消息内容："+message.ToString());
            channel.WriteAndFlushAsync(msgWrapper);
        }


        return true;
    }

    private  void OnDestroy()
    {
        disconnect();

    }




}


public class MsgCodecs : MessageToMessageCodec<IByteBuffer, MsgWrapper>
{
    public override void ChannelActive(IChannelHandlerContext context)
    {
        NettyClient.Instance.isRunning = true;
        Debug.Log("服务器连接成功！");
    }

    public override void ChannelInactive(IChannelHandlerContext context)
    {
        //清理地图中的数据
        NettyClient.Instance.disconnect();
        foreach (var instancePlayer in GameMap.Instance.players)
        {
            GameObject.DestroyImmediate(instancePlayer);
        }

        GameMap.Instance.players.Clear();
        foreach (var monster in GameMap.Instance.monsters)
        {
            GameObject.DestroyImmediate(monster);
        }

        GameMap.Instance.monsters.Clear();
        Debug.Log("服务器连接已断开！");
    }

    protected override void Encode(IChannelHandlerContext ctx, MsgWrapper msg, List<object> output)
    {
        // Debug.Log("发送消息");
        output.Add(msg.ToByteBuf());

    }

    protected override void Decode(IChannelHandlerContext ctx, IByteBuffer msg, List<object> output)
    {
        Debug.Log("收到消息：" + msg.ReadableBytes);
        if (msg.ReadableBytes < 4)
        {
            Debug.LogError("消息长度小于4");
            return;
        }

        msg.MarkReaderIndex();
        int len = msg.ReadInt();
        if (msg.ReadableBytes < len - 4)
        {
            // Debug.LogError("消息内容不完整，希望数据长度："+len+"  实际长度："+msg.ReadableBytes);
            msg.ResetReaderIndex();
            return;
        }

        int msgId = msg.ReadInt();
        Type msgType = MsgManager.getInstance().getMsgType(msgId);
        if (msgType == null)
        {
            Debug.LogError("消息id对应的类型不存在：" + msgId);
            msg.SetReaderIndex(msg.ReaderIndex + len - 8);
            return;
        }

        IByteBuffer byteBuffer = msg.ReadBytes(len - 8);
        string content = byteBuffer.GetString(0, byteBuffer.ReadableBytes, Encoding.UTF8);
        Debug.Log("[" + DateTime.Now.ToString("hh:mm:ss t z") + "]消息内容：" + content);
        //TODO json使用litjson戒心解析
        // object fromJson = JsonUtility.FromJson(content,msgType);
        object fromJson = JsonMapper.ToObject(content, msgType);
        try
        {
            MsgHandler.Instance.handle(fromJson);
        }
        catch (Exception e)
        {
            UnityEngine.Debug.LogError(e);
        }
    }
}    
    
